//异步工作器
#pragma once

#include <functional>
#include <memory>
#include <mutex>
#include <thread>
#include <condition_variable>

#include "buffer.hpp"


namespace iceLogs
{
    using functor = std::function<void(iceLogs::Buffer&)>;
    enum asyncType
    {
        ASYNC_SAFE,
        ASYNE_UNSAFE
    };
    class AsyncLooper
    {
        public:
            using ptr = std::shared_ptr<AsyncLooper>;
            AsyncLooper(const functor& cb, asyncType looperType = asyncType::ASYNC_SAFE)
            :_thread(std::thread(&AsyncLooper::threadEntry, this))
            ,_stop(false)
            ,_callBack(cb)
            ,_looper_type(looperType)
            {

            }

            ~AsyncLooper()
            {
                stop();
            }

            void push(const char* data, size_t len)
            {
                //1.无限扩容——非安全；  2.固定大小——生产缓冲区满了就阻塞
                std::unique_lock<std::mutex> lock(_mutex);
                //条件变量控制，若缓冲区剩余大小大于数据长度，则可以添加数据
                if(_looper_type == asyncType::ASYNC_SAFE)
                    _cond_pro.wait(lock, [&](){return _pro_buff.writeAbleSize() >= len; });
                //能走下来证明空间足够，可以添加数据，
                _pro_buff.push(data, len);
                //唤醒消费者对数据进行处理
                _cond_con.notify_one();
            }

            void stop()
            {
                _stop = true; //将退出标志设置为true,
                _cond_con.notify_all();//唤醒所有的工作线程
                _thread.join();
            }
        private:
            void threadEntry()//线程函数入口
            {
                while(1)
                {
                    //为互斥锁设置一个生命周期，当缓冲区交换完毕就解锁，不需要对数据处理过程加锁
                    {
                        //1.判断生产缓冲区有没有数据，有则交换，无则阻塞
                        std::unique_lock<std::mutex> lock(_mutex);
                        if(_stop && _pro_buff.empty()) break;
                        _cond_con.wait(lock, [&](){ return _stop || !_pro_buff.empty(); });
                        _con_buff.swap(_pro_buff);
                        //2.唤醒生产者，
                        if(_looper_type == asyncType::ASYNC_SAFE)
                            _cond_pro.notify_all();
                    }
                    //3.被唤醒后，对消费缓冲区进行数据处理
                    _callBack(_con_buff);
                    //4.初始化消费缓冲区
                    _con_buff.reset();
                }
            }
        private:
            functor _callBack;  //具体对缓冲区数据处理的回调函数 由异步工作器使用者传入
        private:
            std::atomic<bool> _stop;//工作器停止标识 
            asyncType _looper_type;
            Buffer _pro_buff;//生产缓冲区
            Buffer _con_buff;//消费缓冲区
            std::mutex _mutex;//锁
            std::condition_variable _cond_pro;//生产环境变量
            std::condition_variable _cond_con;//消费环境变量
            std::thread _thread;//异步工作器对应的线程

    };
}